package com.jinlia.show.gateway.plugin.filter;

import com.auth0.jwt.exceptions.TokenExpiredException;
import com.jinlia.show.common.core.utils.JavaJwtUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;
import java.util.Map;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;

/**
 * 安全前置过滤器
 */
public class SecurityGlobalFilter implements GlobalFilter {
    private static final Logger logger = LoggerFactory.getLogger(SecurityGlobalFilter.class);

    final long needRefreshTimeMillis = 5 * 60 * 1000;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        Map<String, Object> metadata = route.getMetadata();
        Boolean needRefreshToken = Boolean.FALSE;
        String s = exchange.getRequest().getURI().getPath();
        if (!(Boolean) metadata.get("needAuth")) {//无需校验的服务
            return chain.filter(exchange);
        }
        if (!exchange.getRequest().getHeaders().keySet().contains("authorization")) {//需要检验，但没有带校验的数据
            return chain.filter(exchange);
        }
        //获取待校验的数据
        try {
            Date date = JavaJwtUtils.checkIndate(exchange.getRequest().getHeaders().get("authorization").get(0));
            if ((date.getTime() - System.currentTimeMillis()) < needRefreshTimeMillis) { //小于5分钟
                //刷新token
                needRefreshToken = Boolean.TRUE;
            }
        } catch (TokenExpiredException tokenExpiredException) {
            throw new RuntimeException("登录失效,请重新登录");
        }
        //后置操作
        Boolean finalNeedRefreshToken = needRefreshToken;
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            if (finalNeedRefreshToken) {
                //刷新token
                exchange.getResponse().getHeaders().set("authorization", JavaJwtUtils.refreshToken(exchange.getRequest().getHeaders().get("authorization").get(0)));
                exchange.getResponse().getHeaders().set("Access-Control-Expose-Headers", "authorization");
            }
        }));
    }
}
